package com.headfirst.singleton.version3;

/**
 * 饱汉式单例模式写法三之双重检查加锁(double-check locking):
 * 优点：解决了多线程安全问题的同时，也兼顾了性能
 * 缺点：不适用于JDK1.4及更早的版本（推荐使用）
 * 
 * 原理：在同步锁的基础上，添加1层 if判断：若单例已创建，则不需再执行加锁操作就可获取实例，从而提高性能
 * 
 * 
 * // 说明
 * // 校验锁1：第1个if
 * // 作用：若单例已创建，则直接返回已创建的单例，无需再执行加锁操作
 * // 即直接跳到执行 return ourInstance
 *
 * // 校验锁2：第2个 if 
 * // 作用：防止多次创建单例问题
 * // 原理
 *   // 1. 线程A调用newInstance()，当运行到②位置时，此时线程B也调用了newInstance()
 *   // 2. 因线程A并没有执行instance = new Singleton();，此时instance仍为空，因此线程B能突破第1层 if 判断，运行到①位置等待synchronized中的A线程执行完毕
 *   // 3. 当线程A释放同步锁时，单例已创建，即instance已非空
 *   // 4. 此时线程B 从①开始执行到位置②。此时第2层 if 判断 = 为空（单例已创建），因此也不会创建多余的实例
 */
public class Singleton_3 {
    
    private volatile static Singleton_3 uniqueInstance;
    
    private Singleton_3(){}
    
    public static Singleton_3 getInstance(){
        if(uniqueInstance == null){ // 1
            synchronized (Singleton_3.class){ // 2
                if(uniqueInstance == null){
                    uniqueInstance = new Singleton_3();
                }
            }
        }
        return uniqueInstance;
    }
}
